package str;

import java.util.ArrayList;
import java.util.List;

public class EmailParser {

    // 常见邮箱域名后缀
    private static final String[] DOMAINS = {
            "com", "cn", "net", "org", "edu", "gov", "io"
    };

    public static List<String> parseEmails(String text) {
        List<String> emails = new ArrayList<>();
        char[] chars = text.toCharArray();
        int start = -1, atPos = -1, dotPos = -1;

        for (int i = 0; i < chars.length; i++) {
            char c = chars[i];

            // 检测@符号位置
            if (c == '@' && start != -1) {
                atPos = i;
                continue;
            }

            // 检测域名分隔符
            if (c == '.' && atPos != -1) {
                dotPos = i;
                continue;
            }

            // 验证字符有效性
            if (isValidChar(c, start, atPos, dotPos)) {
                if (start == -1) start = i;
            } else {
                if (isCompleteEmail(start, atPos, dotPos, i, chars)) {
                    emails.add(new String(chars, start, i - start));
                }
                start = atPos = dotPos = -1;
            }
        }
        return emails;
    }

    private static boolean isValidChar(char c, int start, int atPos, int dotPos) {
        // 用户名部分允许的字符
        if (atPos == -1) {
            return Character.isLetterOrDigit(c)
                    || c == '.' || c == '_' || c == '-' || c == '+';
        }
        // 域名部分允许的字符
        return Character.isLetterOrDigit(c) || c == '.' || c == '-';
    }

    private static boolean isCompleteEmail(int start, int atPos,
                                           int dotPos, int end, char[] chars) {
        if (start == -1 || atPos == -1 || dotPos == -1) return false;
        if (atPos <= start || dotPos <= atPos || end <= dotPos) return false;

        // 验证域名后缀
        String suffix = new String(chars, dotPos + 1, end - dotPos - 1);
        for (String domain : DOMAINS) {
            if (domain.equalsIgnoreCase(suffix)) {
                return true;
            }
        }
        return false;
    }
//
//    public static void main(String[] args) {
//        String mailContent = "联系：support@company.com 或 admin@test.org.cn";
//
//        List<String> list = parseEmails(mailContent);
//        for (String itemStr : list){
//            System.out.println(itemStr);
//        }
//
//    }
//


    //


    // 邮箱地址状态枚举
    private enum State {
        START, LOCAL_PART, AT_SYMBOL, DOMAIN, DOT, TLD
    }

    public static List<String> extract(String text) {
        List<String> emails = new ArrayList<>();
        StringBuilder current = new StringBuilder();
        State state = State.START;
        int validLength = 0;

        for (char c : text.toCharArray()) {
            switch (state) {
                case START:
                    if (isLocalPartChar(c)) {
                        current.append(c);
                        state = State.LOCAL_PART;
                        validLength++;
                    }
                    break;

                case LOCAL_PART:
                    if (c == '@') {
                        current.append(c);
                        state = State.AT_SYMBOL;
                        validLength++;
                    } else if (isLocalPartChar(c)) {
                        current.append(c);
                        validLength++;
                    } else {
                        reset(current, state);
                    }
                    break;

                case AT_SYMBOL:
                    if (isDomainChar(c)) {
                        current.append(c);
                        state = State.DOMAIN;
                        validLength++;
                    } else {
                        reset(current, state);
                    }
                    break;

                case DOMAIN:
                    if (c == '.') {
                        current.append(c);
                        state = State.DOT;
                        validLength++;
                    } else if (isDomainChar(c)) {
                        current.append(c);
                        validLength++;
                    } else {
                        reset(current, state);
                    }
                    break;

                case DOT:
                    if (isDomainChar(c)) {
                        current.append(c);
                        state = State.TLD;
                        validLength++;
                        emails.add(current.toString());
                        reset(current, state);
                    } else {
                        reset(current, state);
                    }
                    break;
            }
        }
        return emails;
    }

    private static boolean isLocalPartChar(char c) {
        return Character.isLetterOrDigit(c)
                || c == '.' || c == '_' || c == '-' || c == '+';
    }

    private static boolean isDomainChar(char c) {
        return Character.isLetterOrDigit(c) || c == '-';
    }

    private static void reset(StringBuilder sb, State state) {
        sb.setLength(0);
        state = State.START;
    }

//    public static void main(String[] args) {
//        String mail = "联系：user@example.com 和 support@test.org";
//        System.out.println(extract(mail)); // 输出 [user@example.com, support@test.org]
//
//
//        List<String> list = extract(mail);
//        for (String itemStr : list){
//            System.out.println(itemStr);
//        }
//
//
//    }



    public static List<String> extractEmails(String emailContent) {
        List<String> emails = new ArrayList<>();
        int start = -1; // 邮箱起始位置
        boolean foundAt = false;
        boolean foundDotAfterAt = false;

        for (int i = 0; i < emailContent.length(); i++) {
            char c = emailContent.charAt(i);

            // 检测邮箱起始位置（字母或数字）
            if (start == -1 && Character.isLetterOrDigit(c)) {
                start = i;
            }

            // 检测到 @ 符号
            if (c == '@' && start != -1) {
                foundAt = true;
            }

            // 在 @ 后检测到 . 符号
            if (foundAt && c == '.') {
                foundDotAfterAt = true;
            }

            // 检测邮箱结束位置（非合法字符或文本结尾）
            if (start != -1 && (isSeparator(c) || i == emailContent.length() - 1)) {
                if (foundAt && foundDotAfterAt) {
                    // 验证域名后缀（如 .com）
                    int dotIndex = emailContent.lastIndexOf('.', i);
                    if (dotIndex > emailContent.indexOf('@') && i - dotIndex >= 3) { // 后缀至少2字符
                        String email = emailContent.substring(start, i).trim();
                        emails.add(email);
                    }
                }
                // 重置状态
                start = -1;
                foundAt = false;
                foundDotAfterAt = false;
            }
        }
        return emails;
    }

    private static boolean isSeparator(char c) {
        return c == ' ' || c == ',' || c == ';' || c == '\n' || c == '\r';
    }

//    public static void main(String[] args) {
//        String emailText = "Contact: support@example.com; sales@domain.co.uk. Invalid: user@.com";
//        List<String> emails = extractEmails(emailText);
////        System.out.println(emails); // 输出: [support@example.com, sales@domain.co.uk]
//
//
//        //
////        List<String> list = extract(mail);
//        for (String itemStr : emails){
//            System.out.println(itemStr);
//        }
//
//
//
//    }


    /**
     * 有效方法，获取text中的所有邮箱
     * @param text
     * @return
     */
    public static List<String> getListsEmails(String text) {
        List<String> result = new ArrayList<>();
        int n = text.length();
        boolean inEmail = false;
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < n; i++) {
            char c = text.charAt(i);

            // 判断当前字符是否是合法邮箱字符
            if (isValidEmailChar(c)) {
                if (!inEmail) {
                    // 开始一个新的邮箱地址
                    inEmail = true;
                    sb = new StringBuilder();
                }
                sb.append(c);
            } else {
                if (inEmail) {
                    // 结束邮箱地址
                    String email = sb.toString();
                    if (isValidEmail(email)) {
                        result.add(email);
                    }
                    inEmail = false;
                }
            }
        }

        // 处理最后可能未关闭的邮箱
        if (inEmail) {
            String email = sb.toString();
            if (isValidEmail(email)) {
                result.add(email);
            }
        }

        return result;
    }

    /**
     *  判断字符是否是邮箱允许的字符 ， 把内容范围进行了规定
     * @param c
     * @return
     */
    private static boolean isValidEmailChar(char c) {

//        Character.isLetterOrDigit是Java中Character类的一个静态方法，
//        用于判断指定字符是否为字母或数字，若是则返回true，否则返回false。‌

        return Character.isLetterOrDigit(c) || "_-@.".indexOf(c) >= 0;
    }

    // 简单验证邮箱结构
    private static boolean isValidEmail(String email) {
        int atPos = email.indexOf('@');
        int lastDot = email.lastIndexOf('.');

        // 必须包含 '@' 和 '.'，并且 '@' 在 '.' 前面
        return atPos > 0 && lastDot > atPos + 1 && lastDot < email.length() - 1;
    }

    // 测试方法
    public static void main(String[] args) {
        String sampleText = "Contact: support0000@example.com; sales@domain.co.uk. Invalid: user@.com 联系我: 000john.doe@example.com 或者 jane-doe_123@test-mail.co.uk, 不要发给 invalid-email@domain  或 wrong@domain";
        List<String> emails = getListsEmails(sampleText);
        System.out.println("找到的邮箱：");
        for (String email : emails) {
            System.out.println(email);
        }
    }





}
